package org.zjx.util;

import com.alibaba.fastjson2.JSON;
import lombok.SneakyThrows;
import org.zjx.action.basic.IdentifyErrorAction;
import org.zjx.core.IWindow;
import org.zjx.entity.Font;
import org.zjx.entity.ParagraphBean;
import org.zjx.enums.FontType;
import org.zjx.identify.FontUtil;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class IdentifyFontUtil {
    private static final String identifyResultTag = "identifyResult";
    public static Map<FontType, List<Font>> fontMap = new HashMap<>();


    public static List<ParagraphBean.Word> identifyFont(IWindow window,BufferedImage screen, Rectangle rectangle, List<Color> colors, FontType fontType, int fontHeight, boolean reverse) {
        List<ParagraphBean.Word> words = identify(window,rectangle == null ? screen : ImageUtil.cutImage(screen, rectangle), colors, getFontAttributes(fontType), fontHeight, reverse);

        if (words != null && rectangle != null) {
            for (ParagraphBean.Word word : words) {
                Rectangle wordRectangle = word.getRectangle();
                wordRectangle.x = wordRectangle.x + rectangle.x;
                wordRectangle.y = wordRectangle.y + rectangle.y;
            }
        }
        return words;
    }

    public static List<ParagraphBean.Word> identify(IWindow window,BufferedImage image, List<Color> colors, List<Font> fonts, int fontHeight, boolean reverse) {
        ParagraphBean paragraphBean = new ParagraphBean();
        paragraphBean.add(FontUtil.categories(identifyResultTag, colors, image, fonts, fontHeight, reverse));
        if (paragraphBean.getChildren() == null || paragraphBean.getChildren().isEmpty()) return null;
        List<ParagraphBean.Word> words = paragraphBean.getChildren().get(0).getWords();
        if (words == null || words.isEmpty()) return null;
        for (ParagraphBean.Word word : words) {
            if (word.getName().contains("null")) {
                //记录错误/未记录字库 图片
                new IdentifyErrorAction(window, image).execute();
                word.setName(word.getName().replace("null", ""));
                break;
            }
        }
        return words;
    }

    @SneakyThrows
    public static List<Font> getFontAttributes(FontType fontType) {
        if (fontMap.containsKey(fontType)) {
            return fontMap.get(fontType);
        }
        String filePath = "fonts/" + fontType.getName() + ".json";
        String json = readFileAsString(Paths.get(filePath));
        List<Font> fonts = JSON.parseArray(json, Font.class);
        if (!fonts.isEmpty()) fontMap.put(fontType, fonts);
        return fonts;
    }

    /**
     * 高效、健壮的文件读取方法（兼容 Java 8）
     */
    private static String readFileAsString(Path path) throws IOException {
        // 检查文件是否存在
        if (!Files.exists(path)) {
            throw new FileNotFoundException("文件不存在: " + path);
        }

        // 检查是否为文件
        if (!Files.isRegularFile(path)) {
            throw new IOException("路径不是文件: " + path);
        }

        // 估计文件大小
        long fileSize = Files.size(path);
        int initialCapacity = (fileSize > 0 && fileSize < Integer.MAX_VALUE) ?
                (int) fileSize : 16384; // 16KB 默认

        try (
                InputStream inputStream = Files.newInputStream(path);
                Reader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8)) {
            StringBuilder content = new StringBuilder(initialCapacity);
            char[] buffer = new char[16384]; // 16KB 缓冲区
            int charsRead;

            while ((charsRead = reader.read(buffer)) != -1) {
                content.append(buffer, 0, charsRead);
            }

            return content.toString();
        } catch (IOException e) {
            throw new IOException("读取文件失败: " + path, e);
        }
    }
}
